<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
<meta name="viewport" content="width=device-width">
<meta name="theme-color" content="#222"><meta name="generator" content="Hexo 6.3.0">

  <link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-next.png">
  <link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32-next.png">
  <link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16-next.png">
  <link rel="mask-icon" href="/images/logo.svg" color="#222">

<link rel="stylesheet" href="/css/main.css">



<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.2/css/all.min.css" integrity="sha256-CTSx/A06dm1B063156EVh15m6Y67pAjZZaQc89LLSrU=" crossorigin="anonymous">
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.1.1/animate.min.css" integrity="sha256-PR7ttpcvz8qrF57fur/yAx1qXMFJeJFiA6pSzWi0OIE=" crossorigin="anonymous">
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/fancyapps-ui/5.0.24/fancybox/fancybox.css" integrity="sha256-vQkngPS8jiHHH0I6ABTZroZk8NPZ7b+MUReOFE9UsXQ=" crossorigin="anonymous">

<script class="next-config" data-name="main" type="application/json">{"hostname":"rjyblog.gitee.io","root":"/","images":"/images","scheme":"Pisces","darkmode":false,"version":"8.18.2","exturl":false,"sidebar":{"position":"left","display":"post","padding":18,"offset":12},"copycode":{"enable":true,"style":null},"fold":{"enable":false,"height":500},"bookmark":{"enable":false,"color":"#222","save":"auto"},"mediumzoom":false,"lazyload":false,"pangu":false,"comments":{"style":"tabs","active":null,"storage":true,"lazyload":false,"nav":null},"stickytabs":false,"motion":{"enable":true,"async":false,"transition":{"menu_item":"fadeInDown","post_block":"fadeIn","post_header":"fadeInDown","post_body":"fadeInDown","coll_header":"fadeInLeft","sidebar":"fadeInUp"}},"prism":false,"i18n":{"placeholder":"搜索...","empty":"没有找到任何搜索结果：${query}","hits_time":"找到 ${hits} 个搜索结果（用时 ${time} 毫秒）","hits":"找到 ${hits} 个搜索结果"},"path":"/search.xml","localsearch":{"enable":true,"trigger":"auto","top_n_per_article":1,"unescape":false,"preload":false}}</script><script src="/js/config.js"></script>

    <meta name="description" content="Java线程池源码详解">
<meta property="og:type" content="article">
<meta property="og:title" content="Java线程池源码详解">
<meta property="og:url" content="https://rjyblog.gitee.io/posts/271b6343.html">
<meta property="og:site_name" content="任建勇的博客">
<meta property="og:description" content="Java线程池源码详解">
<meta property="og:locale" content="zh_CN">
<meta property="article:published_time" content="2023-08-23T07:59:34.000Z">
<meta property="article:modified_time" content="2023-09-21T03:18:49.841Z">
<meta property="article:author" content="Jason">
<meta property="article:tag" content="Android">
<meta property="article:tag" content="Java">
<meta name="twitter:card" content="summary">


<link rel="canonical" href="https://rjyblog.gitee.io/posts/271b6343.html">



<script class="next-config" data-name="page" type="application/json">{"sidebar":"","isHome":false,"isPost":true,"lang":"zh-CN","comments":true,"permalink":"https://rjyblog.gitee.io/posts/271b6343.html","path":"posts/271b6343.html","title":"Java线程池源码详解"}</script>

<script class="next-config" data-name="calendar" type="application/json">""</script>
<title>Java线程池源码详解 | 任建勇的博客</title>
  








  <noscript>
    <link rel="stylesheet" href="/css/noscript.css">
  </noscript>
</head>

<body itemscope itemtype="http://schema.org/WebPage" class="use-motion">
  <div class="headband"></div>

  <main class="main">
    <div class="column">
      <header class="header" itemscope itemtype="http://schema.org/WPHeader"><div class="site-brand-container">
  <div class="site-nav-toggle">
    <div class="toggle" aria-label="切换导航栏" role="button">
        <span class="toggle-line"></span>
        <span class="toggle-line"></span>
        <span class="toggle-line"></span>
    </div>
  </div>

  <div class="site-meta">

    <a href="/" class="brand" rel="start">
      <i class="logo-line"></i>
      <p class="site-title">任建勇的博客</p>
      <i class="logo-line"></i>
    </a>
  </div>

  <div class="site-nav-right">
    <div class="toggle popup-trigger" aria-label="搜索" role="button">
        <i class="fa fa-search fa-fw fa-lg"></i>
    </div>
  </div>
</div>



<nav class="site-nav">
  <ul class="main-menu menu"><li class="menu-item menu-item-home"><a href="/" rel="section"><i class="fa fa-home fa-fw"></i>首页</a></li><li class="menu-item menu-item-tags"><a href="/tags/" rel="section"><i class="fa fa-tags fa-fw"></i>标签</a></li><li class="menu-item menu-item-categories"><a href="/categories/" rel="section"><i class="fa fa-th fa-fw"></i>分类</a></li>
      <li class="menu-item menu-item-search">
        <a role="button" class="popup-trigger"><i class="fa fa-search fa-fw"></i>搜索
        </a>
      </li>
  </ul>
</nav>



  <div class="search-pop-overlay">
    <div class="popup search-popup"><div class="search-header">
  <span class="search-icon">
    <i class="fa fa-search"></i>
  </span>
  <div class="search-input-container">
    <input autocomplete="off" autocapitalize="off" maxlength="80"
           placeholder="搜索..." spellcheck="false"
           type="search" class="search-input">
  </div>
  <span class="popup-btn-close" role="button">
    <i class="fa fa-times-circle"></i>
  </span>
</div>
<div class="search-result-container no-result">
  <div class="search-result-icon">
    <i class="fa fa-spinner fa-pulse fa-5x"></i>
  </div>
</div>

    </div>
  </div>

</header>
        
  
  <aside class="sidebar">

    <div class="sidebar-inner sidebar-nav-active sidebar-toc-active">
      <ul class="sidebar-nav">
        <li class="sidebar-nav-toc">
          文章目录
        </li>
        <li class="sidebar-nav-overview">
          站点概览
        </li>
      </ul>

      <div class="sidebar-panel-container">
        <!--noindex-->
        <div class="post-toc-wrap sidebar-panel">
            <div class="post-toc animated"><ol class="nav"><li class="nav-item nav-level-2"><a class="nav-link" href="#%E7%BA%BF%E7%A8%8B%E6%B1%A0%E7%BA%BF%E7%A8%8B%E6%95%B0%E9%87%8F%E7%AE%A1%E7%90%86"><span class="nav-text">线程池线程数量管理</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%8F%90%E4%BA%A4%E6%96%B0%E4%BB%BB%E5%8A%A1"><span class="nav-text">提交新任务</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%89%A7%E8%A1%8C%E4%BB%BB%E5%8A%A1"><span class="nav-text">执行任务</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E7%BA%BF%E7%A8%8B%E6%B1%A0%E7%8A%B6%E6%80%81"><span class="nav-text">线程池状态</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E7%BA%BF%E7%A8%8B%E6%B1%A0%E6%8E%92%E9%98%9F%E7%AD%96%E7%95%A5"><span class="nav-text">线程池排队策略</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%8F%82%E8%80%83%E6%96%87%E6%A1%A3"><span class="nav-text">参考文档</span></a></li></ol></div>
        </div>
        <!--/noindex-->

        <div class="site-overview-wrap sidebar-panel">
          <div class="site-author animated" itemprop="author" itemscope itemtype="http://schema.org/Person">
    <img class="site-author-image" itemprop="image" alt="Jason"
      src="/images/avatar.png">
  <p class="site-author-name" itemprop="name">Jason</p>
  <div class="site-description" itemprop="description"></div>
</div>
<div class="site-state-wrap animated">
  <nav class="site-state">
      <div class="site-state-item site-state-posts">
        <a href="/archives/">
          <span class="site-state-item-count">66</span>
          <span class="site-state-item-name">日志</span>
        </a>
      </div>
      <div class="site-state-item site-state-categories">
          <a href="/categories/">
        <span class="site-state-item-count">13</span>
        <span class="site-state-item-name">分类</span></a>
      </div>
      <div class="site-state-item site-state-tags">
          <a href="/tags/">
        <span class="site-state-item-count">23</span>
        <span class="site-state-item-name">标签</span></a>
      </div>
  </nav>
</div>

        </div>
      </div>
    </div>

    
  </aside>


    </div>

    <div class="main-inner post posts-expand">


  


<div class="post-block">
  
  

  <article itemscope itemtype="http://schema.org/Article" class="post-content" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="https://rjyblog.gitee.io/posts/271b6343.html">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.png">
      <meta itemprop="name" content="Jason">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="任建勇的博客">
      <meta itemprop="description" content="">
    </span>

    <span hidden itemprop="post" itemscope itemtype="http://schema.org/CreativeWork">
      <meta itemprop="name" content="Java线程池源码详解 | 任建勇的博客">
      <meta itemprop="description" content="Java线程池源码详解">
    </span>
      <header class="post-header">
        <h1 class="post-title" itemprop="name headline">
          Java线程池源码详解
        </h1>

        <div class="post-meta-container">
          <div class="post-meta">
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar"></i>
      </span>
      <span class="post-meta-item-text">发表于</span>

      <time title="创建时间：2023-08-23 15:59:34" itemprop="dateCreated datePublished" datetime="2023-08-23T15:59:34+08:00">2023-08-23</time>
    </span>
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar-check"></i>
      </span>
      <span class="post-meta-item-text">更新于</span>
      <time title="修改时间：2023-09-21 11:18:49" itemprop="dateModified" datetime="2023-09-21T11:18:49+08:00">2023-09-21</time>
    </span>
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-folder"></i>
      </span>
      <span class="post-meta-item-text">分类于</span>
        <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
          <a href="/categories/Java/" itemprop="url" rel="index"><span itemprop="name">Java</span></a>
        </span>
    </span>

  
</div>

            <div class="post-description">Java线程池源码详解</div>
        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody"><p>线程池具备如下两个方面的优势：</p>
<ol>
<li>当需要创建大量异步任务时会改善应用性能，因为线程池减少了任务的调用开销；</li>
<li>可以更好的管理线程，比如监控线程使用情况、系统调优等；</li>
</ol>
<p>下面是线程池类图结构：</p>
<?xml version="1.0" encoding="us-ascii" standalone="no"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" contentStyleType="text/css" height="688px" preserveAspectRatio="none" style="width:380px;height:688px;background:#FFFFFF;" version="1.1" viewBox="0 0 380 688" width="380px" zoomAndPan="magnify"><defs/><g><!--class Executor--><g id="elem_Executor"><rect codeLine="1" fill="#F1F1F1" height="64.2969" id="Executor" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="256" x="17" y="7"/><ellipse cx="109.25" cy="23" fill="#B4A7E5" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M110.2031,19.7813 L111.9219,19.7813 C112.3125,19.7813 112.5,19.75 112.625,19.6719 C112.8906,19.5156 113.0313,19.2344 113.0313,18.9375 C113.0313,18.6719 112.9219,18.4063 112.6875,18.2344 C112.5156,18.125 112.375,18.0938 111.9219,18.0938 L106.7813,18.0938 C106.3438,18.0938 106.2188,18.1094 106.0625,18.2031 C105.8125,18.3594 105.6563,18.6563 105.6563,18.9375 C105.6563,19.2188 105.7969,19.4688 106.0156,19.6406 C106.1719,19.75 106.3594,19.7813 106.7813,19.7813 L108.5,19.7813 L108.5,26.2969 L106.7813,26.2969 C106.3438,26.2969 106.2188,26.3125 106.0625,26.4219 C105.8125,26.5781 105.6563,26.8594 105.6563,27.1563 C105.6563,27.4063 105.7969,27.6719 106.0156,27.8281 C106.1719,27.9531 106.375,28 106.7813,28 L111.9219,28 C112.6719,28 113.0313,27.7188 113.0313,27.1563 C113.0313,26.875 112.9219,26.625 112.6875,26.4531 C112.5156,26.3281 112.375,26.2969 111.9219,26.2969 L110.2031,26.2969 L110.2031,19.7813 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" font-style="italic" lengthAdjust="spacing" textLength="63" x="129.75" y="27.8467">Executor</text><line style="stroke:#181818;stroke-width:0.5;" x1="18" x2="272" y1="39" y2="39"/><line style="stroke:#181818;stroke-width:0.5;" x1="18" x2="272" y1="47" y2="47"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="244" x="23" y="63.9951">void execute(Runnable command)</text></g><!--class ExecutorService--><g id="elem_ExecutorService"><rect codeLine="4" fill="#F1F1F1" height="96.8906" id="ExecutorService" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="276" x="7" y="132"/><ellipse cx="82.75" cy="148" fill="#B4A7E5" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M83.7031,144.7813 L85.4219,144.7813 C85.8125,144.7813 86,144.75 86.125,144.6719 C86.3906,144.5156 86.5313,144.2344 86.5313,143.9375 C86.5313,143.6719 86.4219,143.4063 86.1875,143.2344 C86.0156,143.125 85.875,143.0938 85.4219,143.0938 L80.2813,143.0938 C79.8438,143.0938 79.7188,143.1094 79.5625,143.2031 C79.3125,143.3594 79.1563,143.6563 79.1563,143.9375 C79.1563,144.2188 79.2969,144.4688 79.5156,144.6406 C79.6719,144.75 79.8594,144.7813 80.2813,144.7813 L82,144.7813 L82,151.2969 L80.2813,151.2969 C79.8438,151.2969 79.7188,151.3125 79.5625,151.4219 C79.3125,151.5781 79.1563,151.8594 79.1563,152.1563 C79.1563,152.4063 79.2969,152.6719 79.5156,152.8281 C79.6719,152.9531 79.875,153 80.2813,153 L85.4219,153 C86.1719,153 86.5313,152.7188 86.5313,152.1563 C86.5313,151.875 86.4219,151.625 86.1875,151.4531 C86.0156,151.3281 85.875,151.2969 85.4219,151.2969 L83.7031,151.2969 L83.7031,144.7813 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" font-style="italic" lengthAdjust="spacing" textLength="116" x="103.25" y="152.8467">ExecutorService</text><line style="stroke:#181818;stroke-width:0.5;" x1="8" x2="282" y1="164" y2="164"/><line style="stroke:#181818;stroke-width:0.5;" x1="8" x2="282" y1="172" y2="172"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="264" x="13" y="188.9951">Future&lt;?&gt; submit(Runnable task, ...)</text><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="113" x="13" y="205.292">void shutdown()</text><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="228" x="13" y="221.5889">List&lt;Runnable&gt; shutdownNow()</text></g><!--class AbstractExecutorService--><g id="elem_AbstractExecutorService"><rect fill="#F1F1F1" height="48" id="AbstractExecutorService" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="212" x="39" y="290"/><ellipse cx="54" cy="306" fill="#ADD1B2" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M56.3438,301.6719 C55.4063,301.2344 54.8125,301.0938 53.9375,301.0938 C51.3125,301.0938 49.3125,303.1719 49.3125,305.8906 L49.3125,307.0156 C49.3125,309.5938 51.4219,311.4844 54.3125,311.4844 C55.5313,311.4844 56.6875,311.1875 57.4375,310.6406 C58.0156,310.2344 58.3438,309.7813 58.3438,309.3906 C58.3438,308.9375 57.9531,308.5469 57.4844,308.5469 C57.2656,308.5469 57.0625,308.625 56.875,308.8125 C56.4219,309.2969 56.4219,309.2969 56.2344,309.3906 C55.8125,309.6563 55.125,309.7813 54.3594,309.7813 C52.3125,309.7813 51.0156,308.6875 51.0156,306.9844 L51.0156,305.8906 C51.0156,304.1094 52.2656,302.7969 54,302.7969 C54.5781,302.7969 55.1875,302.9531 55.6563,303.2031 C56.1406,303.4844 56.3125,303.7031 56.4063,304.1094 C56.4688,304.5156 56.5,304.6406 56.6406,304.7656 C56.7813,304.9063 57.0156,305.0156 57.2344,305.0156 C57.5,305.0156 57.7656,304.875 57.9375,304.6563 C58.0469,304.5 58.0781,304.3125 58.0781,303.8906 L58.0781,302.4688 C58.0781,302.0313 58.0625,301.9063 57.9688,301.75 C57.8125,301.4844 57.5313,301.3438 57.2344,301.3438 C56.9375,301.3438 56.7344,301.4375 56.5156,301.75 L56.3438,301.6719 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="180" x="68" y="310.8467">AbstractExecutorService</text><line style="stroke:#181818;stroke-width:0.5;" x1="40" x2="250" y1="322" y2="322"/><line style="stroke:#181818;stroke-width:0.5;" x1="40" x2="250" y1="330" y2="330"/></g><!--class ThreadPoolExecutor--><g id="elem_ThreadPoolExecutor"><rect fill="#F1F1F1" height="48" id="ThreadPoolExecutor" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="177" x="184.5" y="399"/><ellipse cx="199.5" cy="415" fill="#ADD1B2" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M201.8438,410.6719 C200.9063,410.2344 200.3125,410.0938 199.4375,410.0938 C196.8125,410.0938 194.8125,412.1719 194.8125,414.8906 L194.8125,416.0156 C194.8125,418.5938 196.9219,420.4844 199.8125,420.4844 C201.0313,420.4844 202.1875,420.1875 202.9375,419.6406 C203.5156,419.2344 203.8438,418.7813 203.8438,418.3906 C203.8438,417.9375 203.4531,417.5469 202.9844,417.5469 C202.7656,417.5469 202.5625,417.625 202.375,417.8125 C201.9219,418.2969 201.9219,418.2969 201.7344,418.3906 C201.3125,418.6563 200.625,418.7813 199.8594,418.7813 C197.8125,418.7813 196.5156,417.6875 196.5156,415.9844 L196.5156,414.8906 C196.5156,413.1094 197.7656,411.7969 199.5,411.7969 C200.0781,411.7969 200.6875,411.9531 201.1563,412.2031 C201.6406,412.4844 201.8125,412.7031 201.9063,413.1094 C201.9688,413.5156 202,413.6406 202.1406,413.7656 C202.2813,413.9063 202.5156,414.0156 202.7344,414.0156 C203,414.0156 203.2656,413.875 203.4375,413.6563 C203.5469,413.5 203.5781,413.3125 203.5781,412.8906 L203.5781,411.4688 C203.5781,411.0313 203.5625,410.9063 203.4688,410.75 C203.3125,410.4844 203.0313,410.3438 202.7344,410.3438 C202.4375,410.3438 202.2344,410.4375 202.0156,410.75 L201.8438,410.6719 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="145" x="213.5" y="419.8467">ThreadPoolExecutor</text><line style="stroke:#181818;stroke-width:0.5;" x1="185.5" x2="360.5" y1="431" y2="431"/><line style="stroke:#181818;stroke-width:0.5;" x1="185.5" x2="360.5" y1="439" y2="439"/></g><!--class Executors--><g id="elem_Executors"><rect fill="#F1F1F1" height="48" id="Executors" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="103" x="78.5" y="524"/><ellipse cx="93.5" cy="540" fill="#ADD1B2" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M95.8438,535.6719 C94.9063,535.2344 94.3125,535.0938 93.4375,535.0938 C90.8125,535.0938 88.8125,537.1719 88.8125,539.8906 L88.8125,541.0156 C88.8125,543.5938 90.9219,545.4844 93.8125,545.4844 C95.0313,545.4844 96.1875,545.1875 96.9375,544.6406 C97.5156,544.2344 97.8438,543.7813 97.8438,543.3906 C97.8438,542.9375 97.4531,542.5469 96.9844,542.5469 C96.7656,542.5469 96.5625,542.625 96.375,542.8125 C95.9219,543.2969 95.9219,543.2969 95.7344,543.3906 C95.3125,543.6563 94.625,543.7813 93.8594,543.7813 C91.8125,543.7813 90.5156,542.6875 90.5156,540.9844 L90.5156,539.8906 C90.5156,538.1094 91.7656,536.7969 93.5,536.7969 C94.0781,536.7969 94.6875,536.9531 95.1563,537.2031 C95.6406,537.4844 95.8125,537.7031 95.9063,538.1094 C95.9688,538.5156 96,538.6406 96.1406,538.7656 C96.2813,538.9063 96.5156,539.0156 96.7344,539.0156 C97,539.0156 97.2656,538.875 97.4375,538.6563 C97.5469,538.5 97.5781,538.3125 97.5781,537.8906 L97.5781,536.4688 C97.5781,536.0313 97.5625,535.9063 97.4688,535.75 C97.3125,535.4844 97.0313,535.3438 96.7344,535.3438 C96.4375,535.3438 96.2344,535.4375 96.0156,535.75 L95.8438,535.6719 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="71" x="107.5" y="544.8467">Executors</text><line style="stroke:#181818;stroke-width:0.5;" x1="79.5" x2="180.5" y1="556" y2="556"/><line style="stroke:#181818;stroke-width:0.5;" x1="79.5" x2="180.5" y1="564" y2="564"/></g><!--class ForkJoinPool--><g id="elem_ForkJoinPool"><rect fill="#F1F1F1" height="48" id="ForkJoinPool" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="121" x="28.5" y="399"/><ellipse cx="43.5" cy="415" fill="#ADD1B2" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M45.8438,410.6719 C44.9063,410.2344 44.3125,410.0938 43.4375,410.0938 C40.8125,410.0938 38.8125,412.1719 38.8125,414.8906 L38.8125,416.0156 C38.8125,418.5938 40.9219,420.4844 43.8125,420.4844 C45.0313,420.4844 46.1875,420.1875 46.9375,419.6406 C47.5156,419.2344 47.8438,418.7813 47.8438,418.3906 C47.8438,417.9375 47.4531,417.5469 46.9844,417.5469 C46.7656,417.5469 46.5625,417.625 46.375,417.8125 C45.9219,418.2969 45.9219,418.2969 45.7344,418.3906 C45.3125,418.6563 44.625,418.7813 43.8594,418.7813 C41.8125,418.7813 40.5156,417.6875 40.5156,415.9844 L40.5156,414.8906 C40.5156,413.1094 41.7656,411.7969 43.5,411.7969 C44.0781,411.7969 44.6875,411.9531 45.1563,412.2031 C45.6406,412.4844 45.8125,412.7031 45.9063,413.1094 C45.9688,413.5156 46,413.6406 46.1406,413.7656 C46.2813,413.9063 46.5156,414.0156 46.7344,414.0156 C47,414.0156 47.2656,413.875 47.4375,413.6563 C47.5469,413.5 47.5781,413.3125 47.5781,412.8906 L47.5781,411.4688 C47.5781,411.0313 47.5625,410.9063 47.4688,410.75 C47.3125,410.4844 47.0313,410.3438 46.7344,410.3438 C46.4375,410.3438 46.2344,410.4375 46.0156,410.75 L45.8438,410.6719 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="89" x="57.5" y="419.8467">ForkJoinPool</text><line style="stroke:#181818;stroke-width:0.5;" x1="29.5" x2="148.5" y1="431" y2="431"/><line style="stroke:#181818;stroke-width:0.5;" x1="29.5" x2="148.5" y1="439" y2="439"/></g><!--class Worker--><g id="elem_Worker"><rect fill="#F1F1F1" height="48" id="Worker" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="85" x="230.5" y="524"/><ellipse cx="245.5" cy="540" fill="#ADD1B2" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M247.8438,535.6719 C246.9063,535.2344 246.3125,535.0938 245.4375,535.0938 C242.8125,535.0938 240.8125,537.1719 240.8125,539.8906 L240.8125,541.0156 C240.8125,543.5938 242.9219,545.4844 245.8125,545.4844 C247.0313,545.4844 248.1875,545.1875 248.9375,544.6406 C249.5156,544.2344 249.8438,543.7813 249.8438,543.3906 C249.8438,542.9375 249.4531,542.5469 248.9844,542.5469 C248.7656,542.5469 248.5625,542.625 248.375,542.8125 C247.9219,543.2969 247.9219,543.2969 247.7344,543.3906 C247.3125,543.6563 246.625,543.7813 245.8594,543.7813 C243.8125,543.7813 242.5156,542.6875 242.5156,540.9844 L242.5156,539.8906 C242.5156,538.1094 243.7656,536.7969 245.5,536.7969 C246.0781,536.7969 246.6875,536.9531 247.1563,537.2031 C247.6406,537.4844 247.8125,537.7031 247.9063,538.1094 C247.9688,538.5156 248,538.6406 248.1406,538.7656 C248.2813,538.9063 248.5156,539.0156 248.7344,539.0156 C249,539.0156 249.2656,538.875 249.4375,538.6563 C249.5469,538.5 249.5781,538.3125 249.5781,537.8906 L249.5781,536.4688 C249.5781,536.0313 249.5625,535.9063 249.4688,535.75 C249.3125,535.4844 249.0313,535.3438 248.7344,535.3438 C248.4375,535.3438 248.2344,535.4375 248.0156,535.75 L247.8438,535.6719 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="53" x="259.5" y="544.8467">Worker</text><line style="stroke:#181818;stroke-width:0.5;" x1="231.5" x2="314.5" y1="556" y2="556"/><line style="stroke:#181818;stroke-width:0.5;" x1="231.5" x2="314.5" y1="564" y2="564"/></g><!--class Thread--><g id="elem_Thread"><rect fill="#F1F1F1" height="48" id="Thread" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="82" x="291" y="633"/><ellipse cx="306" cy="649" fill="#ADD1B2" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M308.3438,644.6719 C307.4063,644.2344 306.8125,644.0938 305.9375,644.0938 C303.3125,644.0938 301.3125,646.1719 301.3125,648.8906 L301.3125,650.0156 C301.3125,652.5938 303.4219,654.4844 306.3125,654.4844 C307.5313,654.4844 308.6875,654.1875 309.4375,653.6406 C310.0156,653.2344 310.3438,652.7813 310.3438,652.3906 C310.3438,651.9375 309.9531,651.5469 309.4844,651.5469 C309.2656,651.5469 309.0625,651.625 308.875,651.8125 C308.4219,652.2969 308.4219,652.2969 308.2344,652.3906 C307.8125,652.6563 307.125,652.7813 306.3594,652.7813 C304.3125,652.7813 303.0156,651.6875 303.0156,649.9844 L303.0156,648.8906 C303.0156,647.1094 304.2656,645.7969 306,645.7969 C306.5781,645.7969 307.1875,645.9531 307.6563,646.2031 C308.1406,646.4844 308.3125,646.7031 308.4063,647.1094 C308.4688,647.5156 308.5,647.6406 308.6406,647.7656 C308.7813,647.9063 309.0156,648.0156 309.2344,648.0156 C309.5,648.0156 309.7656,647.875 309.9375,647.6563 C310.0469,647.5 310.0781,647.3125 310.0781,646.8906 L310.0781,645.4688 C310.0781,645.0313 310.0625,644.9063 309.9688,644.75 C309.8125,644.4844 309.5313,644.3438 309.2344,644.3438 C308.9375,644.3438 308.7344,644.4375 308.5156,644.75 L308.3438,644.6719 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="50" x="320" y="653.8467">Thread</text><line style="stroke:#181818;stroke-width:0.5;" x1="292" x2="372" y1="665" y2="665"/><line style="stroke:#181818;stroke-width:0.5;" x1="292" x2="372" y1="673" y2="673"/></g><!--class Runnable--><g id="elem_Runnable"><rect fill="#F1F1F1" height="48" id="Runnable" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="99" x="48.5" y="633"/><ellipse cx="63.5" cy="649" fill="#ADD1B2" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M65.8438,644.6719 C64.9063,644.2344 64.3125,644.0938 63.4375,644.0938 C60.8125,644.0938 58.8125,646.1719 58.8125,648.8906 L58.8125,650.0156 C58.8125,652.5938 60.9219,654.4844 63.8125,654.4844 C65.0313,654.4844 66.1875,654.1875 66.9375,653.6406 C67.5156,653.2344 67.8438,652.7813 67.8438,652.3906 C67.8438,651.9375 67.4531,651.5469 66.9844,651.5469 C66.7656,651.5469 66.5625,651.625 66.375,651.8125 C65.9219,652.2969 65.9219,652.2969 65.7344,652.3906 C65.3125,652.6563 64.625,652.7813 63.8594,652.7813 C61.8125,652.7813 60.5156,651.6875 60.5156,649.9844 L60.5156,648.8906 C60.5156,647.1094 61.7656,645.7969 63.5,645.7969 C64.0781,645.7969 64.6875,645.9531 65.1563,646.2031 C65.6406,646.4844 65.8125,646.7031 65.9063,647.1094 C65.9688,647.5156 66,647.6406 66.1406,647.7656 C66.2813,647.9063 66.5156,648.0156 66.7344,648.0156 C67,648.0156 67.2656,647.875 67.4375,647.6563 C67.5469,647.5 67.5781,647.3125 67.5781,646.8906 L67.5781,645.4688 C67.5781,645.0313 67.5625,644.9063 67.4688,644.75 C67.3125,644.4844 67.0313,644.3438 66.7344,644.3438 C66.4375,644.3438 66.2344,644.4375 66.0156,644.75 L65.8438,644.6719 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="67" x="77.5" y="653.8467">Runnable</text><line style="stroke:#181818;stroke-width:0.5;" x1="49.5" x2="146.5" y1="665" y2="665"/><line style="stroke:#181818;stroke-width:0.5;" x1="49.5" x2="146.5" y1="673" y2="673"/></g><g id="elem_GMN21"><path d="M182.5,644.5 L182.5,653 L147.629,657 L182.5,661 L182.5,669.6328 A0,0 0 0 0 182.5,669.6328 L255.5,669.6328 A0,0 0 0 0 255.5,669.6328 L255.5,654.5 L245.5,644.5 L182.5,644.5 A0,0 0 0 0 182.5,644.5 " fill="#FEFFDD" style="stroke:#181818;stroke-width:0.5;"/><path d="M245.5,644.5 L245.5,654.5 L255.5,654.5 L245.5,644.5 " fill="#FEFFDD" style="stroke:#181818;stroke-width:0.5;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="52" x="188.5" y="661.5669">&#29992;&#25143;&#20219;&#21153;</text></g><!--reverse link Executor to ExecutorService--><g id="link_Executor_ExecutorService"><path codeLine="9" d="M145,89.307 C145,107.14 145,111.849 145,131.853 " fill="none" id="Executor-backto-ExecutorService" style="stroke:#181818;stroke-width:1.0;"/><polygon fill="none" points="145,71.307,139,89.307,151,89.307,145,71.307" style="stroke:#181818;stroke-width:1.0;"/></g><!--reverse link ExecutorService to AbstractExecutorService--><g id="link_ExecutorService_AbstractExecutorService"><path codeLine="10" d="M145,247.347 C145,267.909 145,272.999 145,289.703 " fill="none" id="ExecutorService-backto-AbstractExecutorService" style="stroke:#181818;stroke-width:1.0;"/><polygon fill="none" points="145,229.347,139,247.347,151,247.347,145,229.347" style="stroke:#181818;stroke-width:1.0;"/></g><!--reverse link AbstractExecutorService to ThreadPoolExecutor--><g id="link_AbstractExecutorService_ThreadPoolExecutor"><path codeLine="11" d="M186.5841,349.7617 C208.0541,367.7097 223.824,380.892 245.28,398.828 " fill="none" id="AbstractExecutorService-backto-ThreadPoolExecutor" style="stroke:#181818;stroke-width:1.0;"/><polygon fill="none" points="172.774,338.217,182.7359,354.3651,190.4324,345.1583,172.774,338.217" style="stroke:#181818;stroke-width:1.0;"/></g><!--reverse link ThreadPoolExecutor to Executors--><g id="link_ThreadPoolExecutor_Executors"><path codeLine="12" d="M241.5543,451.0477 C215.9883,473.0387 182.303,502.012 156.777,523.968 " fill="none" id="ThreadPoolExecutor-backto-Executors" style="stroke:#181818;stroke-width:1.0;"/><polygon fill="#181818" points="246.103,447.135,236.6714,449.9715,242.3124,450.3956,241.8883,456.0365,246.103,447.135" style="stroke:#181818;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="27" x="212" y="490.0669">new</text></g><!--reverse link ForkJoinPool to Executors--><g id="link_ForkJoinPool_Executors"><path codeLine="13" d="M98.6091,452.8271 C105.9392,474.8181 115.004,502.012 122.323,523.968 " fill="none" id="ForkJoinPool-backto-Executors" style="stroke:#181818;stroke-width:1.0;"/><polygon fill="#181818" points="96.7118,447.135,95.763,456.9381,98.2929,451.8784,103.3525,454.4083,96.7118,447.135" style="stroke:#181818;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="27" x="113" y="490.0669">new</text></g><!--reverse link AbstractExecutorService to ForkJoinPool--><g id="link_AbstractExecutorService_ForkJoinPool"><path codeLine="14" d="M124.5027,354.165 C115.1097,372.113 110.515,380.892 101.1275,398.828 " fill="none" id="AbstractExecutorService-backto-ForkJoinPool" style="stroke:#181818;stroke-width:1.0;"/><polygon fill="none" points="132.849,338.217,119.1867,351.3829,129.8187,356.9471,132.849,338.217" style="stroke:#181818;stroke-width:1.0;"/></g><!--reverse link Worker to Thread--><g id="link_Worker_Thread"><path codeLine="15" d="M291.5961,582.7255 C301.4921,600.6734 309.333,614.8918 319.223,632.8279 " fill="none" id="Worker-backto-Thread" style="stroke:#181818;stroke-width:1.0;"/><polygon fill="#181818" points="285.802,572.217,285.1962,579.4026,291.5961,582.7255,292.2019,575.5399,285.802,572.217" style="stroke:#181818;stroke-width:1.0;"/></g><!--reverse link Worker to Runnable--><g id="link_Worker_Runnable"><path codeLine="16" d="M224.7901,578.4768 C195.4361,596.4247 165.233,614.8918 135.898,632.8279 " fill="none" id="Worker-backto-Runnable" style="stroke:#181818;stroke-width:1.0;"/><polygon fill="#181818" points="235.028,572.217,227.8224,571.9342,224.7901,578.4768,231.9956,578.7595,235.028,572.217" style="stroke:#181818;stroke-width:1.0;"/></g><!--reverse link ThreadPoolExecutor to Worker--><g id="link_ThreadPoolExecutor_Worker"><path codeLine="18" d="M273,459.135 C273,481.126 273,502.012 273,523.968 " fill="none" id="ThreadPoolExecutor-backto-Worker" style="stroke:#181818;stroke-width:1.0;"/><polygon fill="#181818" points="273,447.135,269,453.135,273,459.135,277,453.135,273,447.135" style="stroke:#181818;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="8" x="264.025" y="466.9291">1</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="26" x="243.6688" y="512.9718">0~n</text></g><!--SRC=[VP0zJiD048NxFSN8bOEm1IsoZ2X8WH12W4IzjYTubNW7xSx6IFpKY9eBq743Ybo7dsl4iR4JEJ_RpPjltdjQfHdDIAO8fm-OEYO3ZmAgDoML0TOQ-bTEQvbC458g2gcpWNWMQkto6irKLNDZC7Ji34R7CLYN58gN9YpjU1_2C1miaspkEADI-urshYn7xK7SRI-ez1VPNTVeAGZw-QBVfuPE4ij6fjo7j-ZDqKrkK6QNH9DstPbR2Dnz46z0u0WqbclWaCpuZ9HUeF_8pknLNjnM0nhOwpgjAkq_2KsCODHTpa2ZJgx2_ju_Vr-_lcUpdxSFiQ6nT-ZLJjx1Y_QWiPu3]--></g></svg>

<p>线程池分了两个大类：ThreadPoolExecutor是普通线程池，ForkJoinPool可用理解为是一个轻量级任务的线程池。</p>
<h2 id="线程池线程数量管理"><a href="#线程池线程数量管理" class="headerlink" title="线程池线程数量管理"></a>线程池线程数量管理</h2><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="title function_">ThreadPoolExecutor</span><span class="params">(<span class="type">int</span> corePoolSize,</span></span><br><span class="line"><span class="params">                          <span class="type">int</span> maximumPoolSize,</span></span><br><span class="line"><span class="params">                          <span class="type">long</span> keepAliveTime,</span></span><br><span class="line"><span class="params">                          TimeUnit unit,</span></span><br><span class="line"><span class="params">                          BlockingQueue&lt;Runnable&gt; workQueue,</span></span><br><span class="line"><span class="params">                          ThreadFactory threadFactory,</span></span><br><span class="line"><span class="params">                          RejectedExecutionHandler handler)</span></span><br></pre></td></tr></table></figure>

<ol>
<li>corePoolSize核心线程数: 当线程池的线程数小于corePoolSize时，会创建一个新的线程来执行新任务，即使有线程处于闲置状态。</li>
<li>maximumPoolSize最大线程数：当线程数已经大于corePoolSize，新任务会被优先添加到队列中等待执行。如果任务队列满了导致添加失败，并且线程数小于maximumPoolSize，就会创建新的线程来执行新任务。大于核心线程数的这些线程算是“借”来的，当借来的这些线程的idle时间超过keepAliveTime，就会被回收。回收逻辑在runWorker函数中。</li>
<li>如果线程队列满了，线程数也已经大于maximumPoolSize，就会回调<code>RejectedExecutionHandler.rejectedExecution</code>让调用中来处理任务。</li>
</ol>
<?xml version="1.0" encoding="us-ascii" standalone="no"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" contentStyleType="text/css" height="228px" preserveAspectRatio="none" style="width:580px;height:228px;background:#FFFFFF;" version="1.1" viewBox="0 0 580 228" width="580px" zoomAndPan="magnify"><defs/><g><rect fill="#F1F1F1" height="33.9688" rx="12.5" ry="12.5" style="stroke:#181818;stroke-width:0.5;" width="80" x="237" y="11"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacing" textLength="60" x="247" y="32.1387">&#28155;&#21152;&#26032;&#20219;&#21153;</text><polygon fill="#F1F1F1" points="48,64.9688,114,64.9688,126,76.9688,114,88.9688,48,88.9688,36,76.9688,48,64.9688" style="stroke:#181818;stroke-width:0.5;"/><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacing" textLength="14" x="85" y="99.1792">no</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacing" textLength="66" x="48" y="80.7769">&#26680;&#24515;&#32447;&#31243;&#24050;&#28385;</text><rect fill="#F1F1F1" height="33.9688" rx="12.5" ry="12.5" style="stroke:#181818;stroke-width:0.5;" width="140" x="11" y="121.7734"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacing" textLength="120" x="21" y="142.9121">&#21019;&#24314;&#26680;&#24515;&#32447;&#31243;&#25191;&#34892;&#20219;&#21153;</text><polygon fill="#F1F1F1" points="194,64.9688,260,64.9688,272,76.9688,260,88.9688,194,88.9688,182,76.9688,194,64.9688" style="stroke:#181818;stroke-width:0.5;"/><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacing" textLength="14" x="231" y="99.1792">no</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacing" textLength="66" x="194" y="80.7769">&#20219;&#21153;&#38431;&#21015;&#24050;&#28385;</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacing" textLength="21" x="161" y="74.3745">yes</text><rect fill="#F1F1F1" height="33.9688" rx="12.5" ry="12.5" style="stroke:#181818;stroke-width:0.5;" width="128" x="163" y="121.7734"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacing" textLength="108" x="173" y="142.9121">&#28155;&#21152;&#21040;&#38431;&#21015;&#31561;&#24453;&#25191;&#34892;</text><polygon fill="#F1F1F1" points="357.5,64.9688,434.5,64.9688,446.5,76.9688,434.5,88.9688,357.5,88.9688,345.5,76.9688,357.5,64.9688" style="stroke:#181818;stroke-width:0.5;"/><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacing" textLength="14" x="400" y="99.1792">no</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacing" textLength="77" x="357.5" y="80.7769">&#36798;&#21040;&#26368;&#22823;&#32447;&#31243;&#25968;</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacing" textLength="21" x="324.5" y="74.3745">yes</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacing" textLength="21" x="446.5" y="74.3745">yes</text><rect fill="#F1F1F1" height="33.9688" rx="12.5" ry="12.5" style="stroke:#181818;stroke-width:0.5;" width="128" x="332" y="121.7734"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacing" textLength="108" x="342" y="142.9121">&#21019;&#26032;&#26032;&#32447;&#31243;&#25191;&#34892;&#20219;&#21153;</text><rect fill="#F1F1F1" height="33.9688" rx="12.5" ry="12.5" style="stroke:#181818;stroke-width:0.5;" width="92" x="477.5" y="118.3711"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacing" textLength="72" x="487.5" y="139.5098">&#25191;&#34892;&#25298;&#32477;&#31574;&#30053;</text><ellipse cx="277" cy="206.7422" fill="none" rx="11" ry="11" style="stroke:#222222;stroke-width:1.0;"/><ellipse cx="277" cy="206.7422" fill="#222222" rx="6" ry="6" style="stroke:#222222;stroke-width:1.0;"/><line style="stroke:#181818;stroke-width:1.0;" x1="81" x2="81" y1="88.9688" y2="121.7734"/><polygon fill="#181818" points="77,111.7734,81,121.7734,85,111.7734,81,115.7734" style="stroke:#181818;stroke-width:1.0;"/><line style="stroke:#181818;stroke-width:1.0;" x1="81" x2="81" y1="155.7422" y2="175.7422"/><polygon fill="#181818" points="77,165.7422,81,175.7422,85,165.7422,81,169.7422" style="stroke:#181818;stroke-width:1.0;"/><line style="stroke:#181818;stroke-width:1.0;" x1="227" x2="227" y1="88.9688" y2="121.7734"/><polygon fill="#181818" points="223,111.7734,227,121.7734,231,111.7734,227,115.7734" style="stroke:#181818;stroke-width:1.0;"/><line style="stroke:#181818;stroke-width:1.0;" x1="227" x2="227" y1="155.7422" y2="175.7422"/><polygon fill="#181818" points="223,165.7422,227,175.7422,231,165.7422,227,169.7422" style="stroke:#181818;stroke-width:1.0;"/><line style="stroke:#181818;stroke-width:1.0;" x1="396" x2="396" y1="88.9688" y2="121.7734"/><polygon fill="#181818" points="392,111.7734,396,121.7734,400,111.7734,396,115.7734" style="stroke:#181818;stroke-width:1.0;"/><line style="stroke:#181818;stroke-width:1.0;" x1="396" x2="396" y1="155.7422" y2="175.7422"/><polygon fill="#181818" points="392,165.7422,396,175.7422,400,165.7422,396,169.7422" style="stroke:#181818;stroke-width:1.0;"/><line style="stroke:#181818;stroke-width:1.0;" x1="126" x2="182" y1="76.9688" y2="76.9688"/><polygon fill="#181818" points="172,72.9688,182,76.9688,172,80.9688,176,76.9688" style="stroke:#181818;stroke-width:1.0;"/><line style="stroke:#181818;stroke-width:1.0;" x1="272" x2="345.5" y1="76.9688" y2="76.9688"/><polygon fill="#181818" points="335.5,72.9688,345.5,76.9688,335.5,80.9688,339.5,76.9688" style="stroke:#181818;stroke-width:1.0;"/><line style="stroke:#181818;stroke-width:1.0;" x1="277" x2="277" y1="44.9688" y2="49.9688"/><line style="stroke:#181818;stroke-width:1.0;" x1="277" x2="81" y1="49.9688" y2="49.9688"/><line style="stroke:#181818;stroke-width:1.0;" x1="81" x2="81" y1="49.9688" y2="64.9688"/><polygon fill="#181818" points="77,54.9688,81,64.9688,85,54.9688,81,58.9688" style="stroke:#181818;stroke-width:1.0;"/><line style="stroke:#181818;stroke-width:1.0;" x1="446.5" x2="523.5" y1="76.9688" y2="76.9688"/><line style="stroke:#181818;stroke-width:1.0;" x1="523.5" x2="523.5" y1="76.9688" y2="118.3711"/><polygon fill="#181818" points="519.5,108.3711,523.5,118.3711,527.5,108.3711,523.5,112.3711" style="stroke:#181818;stroke-width:1.0;"/><line style="stroke:#181818;stroke-width:1.0;" x1="523.5" x2="523.5" y1="152.3398" y2="175.7422"/><polygon fill="#181818" points="519.5,165.7422,523.5,175.7422,527.5,165.7422,523.5,169.7422" style="stroke:#181818;stroke-width:1.0;"/><line style="stroke:#181818;stroke-width:1.0;" x1="81" x2="523.5" y1="175.7422" y2="175.7422"/><line style="stroke:#181818;stroke-width:1.0;" x1="277" x2="277" y1="175.7422" y2="195.7422"/><polygon fill="#181818" points="273,185.7422,277,195.7422,281,185.7422,277,189.7422" style="stroke:#181818;stroke-width:1.0;"/><!--SRC=[itgsVVVJhWNFfcruiXl8M6ZDbPcceF5imOwd-vkVxzh_V4Ntq-sRdkrUgAbGaf6Qfw2Hbw_9fQ1WzRHZzjFTkv2LFUjS_c9X3ymGZShKOas5r9pYL91n4D6NC-O_xPYER1pCD8WRddPiW2XvlhRpwRvMY87eHhtOjm-exjcSXgTBbaCjdhe1rJIWsu3U0I9i3WEPem0s4cmnMEvPzwJdk-S-Nplj-TIbG1LvAPbfNCKb-GK0]--></g></svg>

<p><strong>通过一段代码测试一下上述线程数量的限制：</strong></p>
<figure class="highlight kotlin"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">val</span> server: ExecutorService = ThreadPoolExecutor(</span><br><span class="line">    <span class="number">2</span>, <span class="comment">//corePoolSize</span></span><br><span class="line">    <span class="number">10</span>, <span class="comment">//maximumPoolSize</span></span><br><span class="line">    <span class="number">5</span>, TimeUnit.MINUTES,  <span class="comment">//keepAliveTime</span></span><br><span class="line">    LinkedBlockingDeque(<span class="number">5</span>)) <span class="comment">//任务队列，最大容量是5</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span> (i <span class="keyword">in</span> <span class="number">0.</span><span class="number">.20</span>) &#123;</span><br><span class="line">    server.execute &#123; </span><br><span class="line">        println(<span class="string">&quot;task <span class="variable">$i</span> run&quot;</span>)</span><br><span class="line">        Thread.sleep(<span class="built_in">Long</span>.MAX_VALUE)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>上面这段代码的输出为：</p>
<figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">task 0 run</span><br><span class="line">task 1 run</span><br><span class="line">task 7 run</span><br><span class="line">task 8 run</span><br><span class="line">task 9 run</span><br><span class="line">task 10 run</span><br><span class="line">task 11 run</span><br><span class="line">task 12 run</span><br><span class="line">task 13 run</span><br><span class="line">task 14 run</span><br><span class="line">Exception in thread &quot;main&quot; java.util.concurrent.RejectedExecutionException: Task MainKt$$Lambda$16/0x0000017ddf003400@70177ecd rejected from java.util.concurrent.ThreadPoolExecutor@1e80bfe8[Running, pool size = 10, active threads = 10, queued tasks = 5, completed tasks = 0]</span><br><span class="line">	at java.base/java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2065)</span><br><span class="line">	at java.base/java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:833)</span><br><span class="line">	at java.base/java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1365)</span><br><span class="line">	at MainKt.main(Main.kt:20)</span><br></pre></td></tr></table></figure>

<p>从程序的输出可以看出，0、1是通过核心线程来执行，2&#126;5号任务被添加到了队列中等待执行。因为任务队列满了，所以7~14是通过新建线程来执行（线程数没有超过maximumPoolSize）。0、1、7&#126;14共计10个任务，达到了maximumPoolSize设置的最大线程数，所以当添加15号线程时报出了异常。</p>
<h2 id="提交新任务"><a href="#提交新任务" class="headerlink" title="提交新任务"></a>提交新任务</h2><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// ThreadPoolExecutor.java</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">execute</span><span class="params">(Runnable command)</span> &#123;</span><br><span class="line">    <span class="keyword">if</span> (command == <span class="literal">null</span>)</span><br><span class="line">        <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">NullPointerException</span>();</span><br><span class="line">    <span class="type">int</span> <span class="variable">c</span> <span class="operator">=</span> ctl.get();</span><br><span class="line">    <span class="comment">// 1. 如果当前线程池线程数小于corePoolSize，就创建一个新的线程来执行任务</span></span><br><span class="line">    <span class="keyword">if</span> (workerCountOf(c) &lt; corePoolSize) &#123;</span><br><span class="line">        <span class="keyword">if</span> (addWorker(command, <span class="literal">true</span>))</span><br><span class="line">            <span class="keyword">return</span>;</span><br><span class="line">        c = ctl.get();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 2. 线程数已经大于corePoolSize，并且线程池当前是running状态，就把任务添加到队列中等待执行</span></span><br><span class="line">    <span class="keyword">if</span> (isRunning(c) &amp;&amp; workQueue.offer(command)) &#123;</span><br><span class="line">        <span class="type">int</span> <span class="variable">recheck</span> <span class="operator">=</span> ctl.get();</span><br><span class="line">        <span class="keyword">if</span> (! isRunning(recheck) &amp;&amp; remove(command))</span><br><span class="line">            reject(command);</span><br><span class="line">        <span class="keyword">else</span> <span class="keyword">if</span> (workerCountOf(recheck) == <span class="number">0</span>)</span><br><span class="line">            addWorker(<span class="literal">null</span>, <span class="literal">false</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">// 3. 任务队列已满，并且线程数小于maximumPoolSize，则创建新的线程来执行</span></span><br><span class="line">    <span class="keyword">else</span> <span class="keyword">if</span> (!addWorker(command, <span class="literal">false</span>))</span><br><span class="line">        reject(command);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">private</span> <span class="type">boolean</span> <span class="title function_">addWorker</span><span class="params">(Runnable firstTask, <span class="type">boolean</span> core)</span> &#123;</span><br><span class="line">    retry:</span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> <span class="variable">c</span> <span class="operator">=</span> ctl.get();;) &#123;</span><br><span class="line">        <span class="comment">// Check if queue empty only if necessary.</span></span><br><span class="line">        <span class="keyword">if</span> (runStateAtLeast(c, SHUTDOWN) &amp;&amp; </span><br><span class="line">            (runStateAtLeast(c, STOP) || firstTask != <span class="literal">null</span> || workQueue.isEmpty()))</span><br><span class="line">            <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">for</span> (;;) &#123;</span><br><span class="line">            <span class="comment">//a) 添加核心线程：如果线程数量&gt;=corePoolSize返回失败;</span></span><br><span class="line">            <span class="comment">//b) 队列已满，添加非核心新线程，如果线程数量&gt;=maximumPoolSize返回失败</span></span><br><span class="line">            <span class="keyword">if</span> (workerCountOf(c) &gt;= ((core ? corePoolSize : maximumPoolSize) &amp; COUNT_MASK))</span><br><span class="line">                <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line">            <span class="comment">//线程数+1并返回外层的for循环</span></span><br><span class="line">            <span class="keyword">if</span> (compareAndIncrementWorkerCount(c))</span><br><span class="line">                <span class="keyword">break</span> retry;</span><br><span class="line">            c = ctl.get();  <span class="comment">// Re-read ctl</span></span><br><span class="line">            <span class="keyword">if</span> (runStateAtLeast(c, SHUTDOWN))</span><br><span class="line">                <span class="keyword">continue</span> retry;</span><br><span class="line">            <span class="comment">// else CAS failed due to workerCount change; retry inner loop</span></span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="type">boolean</span> <span class="variable">workerStarted</span> <span class="operator">=</span> <span class="literal">false</span>;</span><br><span class="line">    <span class="type">boolean</span> <span class="variable">workerAdded</span> <span class="operator">=</span> <span class="literal">false</span>;</span><br><span class="line">    <span class="type">Worker</span> <span class="variable">w</span> <span class="operator">=</span> <span class="literal">null</span>;</span><br><span class="line">    <span class="keyword">try</span> &#123;</span><br><span class="line">        <span class="comment">// 创建新线程，Worker构造函数中会创新新的Thread</span></span><br><span class="line">        w = <span class="keyword">new</span> <span class="title class_">Worker</span>(firstTask);</span><br><span class="line">        <span class="keyword">final</span> <span class="type">Thread</span> <span class="variable">t</span> <span class="operator">=</span> w.thread;</span><br><span class="line">        <span class="keyword">if</span> (t != <span class="literal">null</span>) &#123;</span><br><span class="line">            <span class="keyword">final</span> <span class="type">ReentrantLock</span> <span class="variable">mainLock</span> <span class="operator">=</span> <span class="built_in">this</span>.mainLock;</span><br><span class="line">            mainLock.lock();</span><br><span class="line">            <span class="keyword">try</span> &#123;</span><br><span class="line">                <span class="comment">// Recheck while holding lock.</span></span><br><span class="line">                <span class="comment">// Back out on ThreadFactory failure or if</span></span><br><span class="line">                <span class="comment">// shut down before lock acquired.</span></span><br><span class="line">                <span class="type">int</span> <span class="variable">c</span> <span class="operator">=</span> ctl.get();</span><br><span class="line"></span><br><span class="line">                <span class="keyword">if</span> (isRunning(c) ||</span><br><span class="line">                    (runStateLessThan(c, STOP) &amp;&amp; firstTask == <span class="literal">null</span>)) &#123;</span><br><span class="line">                    <span class="keyword">if</span> (t.getState() != Thread.State.NEW)</span><br><span class="line">                        <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">IllegalThreadStateException</span>();</span><br><span class="line">                    workers.add(w);</span><br><span class="line">                    workerAdded = <span class="literal">true</span>;</span><br><span class="line">                    <span class="type">int</span> <span class="variable">s</span> <span class="operator">=</span> workers.size();</span><br><span class="line">                    <span class="keyword">if</span> (s &gt; largestPoolSize)</span><br><span class="line">                        largestPoolSize = s;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125; <span class="keyword">finally</span> &#123;</span><br><span class="line">                mainLock.unlock();</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">if</span> (workerAdded) &#123;</span><br><span class="line">                t.start();</span><br><span class="line">                workerStarted = <span class="literal">true</span>;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125; <span class="keyword">finally</span> &#123;</span><br><span class="line">        <span class="keyword">if</span> (! workerStarted)</span><br><span class="line">            addWorkerFailed(w);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> workerStarted;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="执行任务"><a href="#执行任务" class="headerlink" title="执行任务"></a>执行任务</h2><p>线程池中的每个线程对应一个Worker，Worker的首次任务执行完成后，不会立马退出，而是通过getTask()在任务队列中阻塞获取任务，当获取到任务队列中的任务后，就继续执行。如果线程池没有被退出，并且线程数已经超过核心线程数，getTask()中就会以超时的方式阻塞获取任务，超时时间为keepAliveTime，如果发生timeout（keepAliveTime时间后，任务队列中也没有新任务），就会返回null，此时runWorker函数就会走到<code>processWorkerExit</code>的逻辑来回收“借”来的线程，<code>processWorkerExit</code>执行完成后线程就退出了。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">private</span> <span class="keyword">final</span> <span class="keyword">class</span> <span class="title class_">Worker</span></span><br><span class="line">    <span class="keyword">extends</span> <span class="title class_">AbstractQueuedSynchronizer</span></span><br><span class="line">    <span class="keyword">implements</span> <span class="title class_">Runnable</span></span><br><span class="line">&#123;</span><br><span class="line">    ......</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">run</span><span class="params">()</span> &#123;</span><br><span class="line">        runWorker(<span class="built_in">this</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    ......</span><br><span class="line">    <span class="comment">//反复从队列中获取任务并执行</span></span><br><span class="line">    <span class="keyword">final</span> <span class="keyword">void</span> <span class="title function_">runWorker</span><span class="params">(Worker w)</span> &#123;</span><br><span class="line">        <span class="type">Thread</span> <span class="variable">wt</span> <span class="operator">=</span> Thread.currentThread();</span><br><span class="line">        <span class="type">Runnable</span> <span class="variable">task</span> <span class="operator">=</span> w.firstTask;</span><br><span class="line">        w.firstTask = <span class="literal">null</span>;</span><br><span class="line">        w.unlock(); <span class="comment">// allow interrupts</span></span><br><span class="line">        <span class="type">boolean</span> <span class="variable">completedAbruptly</span> <span class="operator">=</span> <span class="literal">true</span>;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            <span class="comment">// 优先执行firstTask，firstTask执行完成后会调用getTask()从队列获取任务来执行</span></span><br><span class="line">            <span class="comment">// 如果getTask()返回null，线程会退出，系统就会回收这个线程</span></span><br><span class="line">            <span class="keyword">while</span> (task != <span class="literal">null</span> || (task = getTask()) != <span class="literal">null</span>) &#123;</span><br><span class="line">                w.lock();</span><br><span class="line">                <span class="comment">// If pool is stopping, ensure thread is interrupted;</span></span><br><span class="line">                <span class="comment">// if not, ensure thread is not interrupted.  This</span></span><br><span class="line">                <span class="comment">// requires a recheck in second case to deal with</span></span><br><span class="line">                <span class="comment">// shutdownNow race while clearing interrupt</span></span><br><span class="line">                <span class="keyword">if</span> ((runStateAtLeast(ctl.get(), STOP) ||</span><br><span class="line">                     (Thread.interrupted() &amp;&amp;</span><br><span class="line">                      runStateAtLeast(ctl.get(), STOP))) &amp;&amp;</span><br><span class="line">                    !wt.isInterrupted())</span><br><span class="line">                    wt.interrupt();</span><br><span class="line">                <span class="keyword">try</span> &#123;</span><br><span class="line">                    beforeExecute(wt, task);</span><br><span class="line">                    <span class="keyword">try</span> &#123;</span><br><span class="line">                        task.run(); <span class="comment">//执行任务</span></span><br><span class="line">                        afterExecute(task, <span class="literal">null</span>);</span><br><span class="line">                    &#125; <span class="keyword">catch</span> (Throwable ex) &#123;</span><br><span class="line">                        afterExecute(task, ex);</span><br><span class="line">                        <span class="keyword">throw</span> ex;</span><br><span class="line">                    &#125;</span><br><span class="line">                &#125; <span class="keyword">finally</span> &#123;</span><br><span class="line">                    task = <span class="literal">null</span>;</span><br><span class="line">                    w.completedTasks++;</span><br><span class="line">                    w.unlock();</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">            completedAbruptly = <span class="literal">false</span>;</span><br><span class="line">        &#125; <span class="keyword">finally</span> &#123;</span><br><span class="line">            processWorkerExit(w, completedAbruptly);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> Runnable <span class="title function_">getTask</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="type">boolean</span> <span class="variable">timedOut</span> <span class="operator">=</span> <span class="literal">false</span>; <span class="comment">// Did the last poll() time out?</span></span><br><span class="line"></span><br><span class="line">        <span class="keyword">for</span> (;;) &#123;</span><br><span class="line">            <span class="type">int</span> <span class="variable">c</span> <span class="operator">=</span> ctl.get();</span><br><span class="line"></span><br><span class="line">            <span class="comment">// Check if queue empty only if necessary.</span></span><br><span class="line">            <span class="keyword">if</span> (runStateAtLeast(c, SHUTDOWN)</span><br><span class="line">                &amp;&amp; (runStateAtLeast(c, STOP) || workQueue.isEmpty())) &#123;</span><br><span class="line">                decrementWorkerCount();</span><br><span class="line">                <span class="keyword">return</span> <span class="literal">null</span>;</span><br><span class="line">            &#125;</span><br><span class="line"></span><br><span class="line">            <span class="type">int</span> <span class="variable">wc</span> <span class="operator">=</span> workerCountOf(c);</span><br><span class="line"></span><br><span class="line">            <span class="comment">// Are workers subject to culling?</span></span><br><span class="line">            <span class="type">boolean</span> <span class="variable">timed</span> <span class="operator">=</span> allowCoreThreadTimeOut || wc &gt; corePoolSize;</span><br><span class="line"></span><br><span class="line">            <span class="comment">//线程数大于maximumPoolSize或者线程的闲置时间超过了keepAliveTime就返回null退出线程</span></span><br><span class="line">            <span class="keyword">if</span> ((wc &gt; maximumPoolSize || (timed &amp;&amp; timedOut))</span><br><span class="line">                &amp;&amp; (wc &gt; <span class="number">1</span> || workQueue.isEmpty())) &#123;</span><br><span class="line">                <span class="keyword">if</span> (compareAndDecrementWorkerCount(c))</span><br><span class="line">                    <span class="keyword">return</span> <span class="literal">null</span>;</span><br><span class="line">                <span class="keyword">continue</span>;</span><br><span class="line">            &#125;</span><br><span class="line"></span><br><span class="line">            <span class="keyword">try</span> &#123;</span><br><span class="line">                <span class="comment">//从队列中获取任务</span></span><br><span class="line">                <span class="type">Runnable</span> <span class="variable">r</span> <span class="operator">=</span> timed ?</span><br><span class="line">                    workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :</span><br><span class="line">                    workQueue.take();</span><br><span class="line">                <span class="keyword">if</span> (r != <span class="literal">null</span>)</span><br><span class="line">                    <span class="keyword">return</span> r;</span><br><span class="line">                timedOut = <span class="literal">true</span>;</span><br><span class="line">            &#125; <span class="keyword">catch</span> (InterruptedException retry) &#123;</span><br><span class="line">                timedOut = <span class="literal">false</span>;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    ......</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="线程池状态"><a href="#线程池状态" class="headerlink" title="线程池状态"></a>线程池状态</h2><ul>
<li>RUNNING: 接收新任务，并且处理队列中的任务；</li>
<li>SHUTDOWN: 不接受新任务，但会继续处理队列中的任务；</li>
<li>STOP: 不接受新任务，不处理队列中的任务，并且会终端正在执行的任务；</li>
<li>TIDYING: 所有任务都已经终止，线程数是0，线程转换到TIDYING状态会运行terminated()方法；</li>
<li>TERMINATED: terminated()运行结束；</li>
</ul>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
 "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 2.40.1 (20161225.0304)
 -->
<!-- Title: %0 Pages: 1 -->
<svg width="234pt" height="385pt"
 viewBox="0.00 0.00 233.59 384.80" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 380.8)">
<title>%0</title>
<polygon fill="#ffffff" stroke="transparent" points="-4,4 -4,-380.8 229.5947,-380.8 229.5947,4 -4,4"/>
<!-- RUNNING -->
<g id="node1" class="node">
<title>RUNNING</title>
<polygon fill="none" stroke="#000000" points="146.5831,-376.8 84.3969,-376.8 84.3969,-340.8 146.5831,-340.8 146.5831,-376.8"/>
<text text-anchor="middle" x="115.49" y="-355.8" font-family="Times,serif" font-size="10.00" fill="#000000">RUNNING</text>
</g>
<!-- SHUTDOWN -->
<g id="node2" class="node">
<title>SHUTDOWN</title>
<polygon fill="none" stroke="#000000" points="112.1923,-291.6 38.7877,-291.6 38.7877,-255.6 112.1923,-255.6 112.1923,-291.6"/>
<text text-anchor="middle" x="75.49" y="-270.6" font-family="Times,serif" font-size="10.00" fill="#000000">SHUTDOWN</text>
</g>
<!-- RUNNING&#45;&gt;SHUTDOWN -->
<g id="edge1" class="edge">
<title>RUNNING&#45;&gt;SHUTDOWN</title>
<path fill="none" stroke="#000000" d="M106.3249,-340.5449C103.5206,-334.878 100.4542,-328.5979 97.7143,-322.8 94.4105,-315.8089 90.928,-308.2141 87.7251,-301.1307"/>
<polygon fill="#000000" stroke="#000000" points="90.8654,-299.58 83.5738,-291.8934 84.4805,-302.4494 90.8654,-299.58"/>
<text text-anchor="middle" x="119.8778" y="-312.9" font-family="Times,serif" font-size="11.00" fill="#000000">shutdown</text>
</g>
<!-- STOP -->
<g id="node3" class="node">
<title>STOP</title>
<polygon fill="none" stroke="#000000" points="181.49,-206.4 127.49,-206.4 127.49,-170.4 181.49,-170.4 181.49,-206.4"/>
<text text-anchor="middle" x="154.49" y="-185.4" font-family="Times,serif" font-size="10.00" fill="#000000">STOP</text>
</g>
<!-- RUNNING&#45;&gt;STOP -->
<g id="edge2" class="edge">
<title>RUNNING&#45;&gt;STOP</title>
<path fill="none" stroke="#000000" d="M130.6484,-340.7479C134.4778,-335.2934 138.16,-329.0777 140.49,-322.8 153.4614,-287.8508 155.7236,-244.5048 155.5737,-216.6522"/>
<polygon fill="#000000" stroke="#000000" points="159.0697,-216.3766 155.4059,-206.4354 152.0707,-216.4916 159.0697,-216.3766"/>
<text text-anchor="middle" x="186.5687" y="-270.3" font-family="Times,serif" font-size="11.00" fill="#000000">shutdownNow</text>
</g>
<!-- SHUTDOWN&#45;&gt;STOP -->
<g id="edge3" class="edge">
<title>SHUTDOWN&#45;&gt;STOP</title>
<path fill="none" stroke="#000000" d="M71.3705,-255.3975C70.1543,-245.4742 70.4503,-233.4147 76.3325,-224.4 77.0064,-223.3672 97.7904,-213.8169 117.7537,-204.8132"/>
<polygon fill="#000000" stroke="#000000" points="119.4092,-207.9064 127.0936,-200.6126 116.5379,-201.5224 119.4092,-207.9064"/>
<text text-anchor="middle" x="108.5687" y="-227.7" font-family="Times,serif" font-size="11.00" fill="#000000">shutdownNow</text>
</g>
<!-- TIDYING -->
<g id="node4" class="node">
<title>TIDYING</title>
<polygon fill="none" stroke="#000000" points="69.1341,-121.2 11.8459,-121.2 11.8459,-85.2 69.1341,-85.2 69.1341,-121.2"/>
<text text-anchor="middle" x="40.49" y="-100.2" font-family="Times,serif" font-size="10.00" fill="#000000">TIDYING</text>
</g>
<!-- SHUTDOWN&#45;&gt;TIDYING -->
<g id="edge4" class="edge">
<title>SHUTDOWN&#45;&gt;TIDYING</title>
<path fill="none" stroke="#000000" d="M60.4198,-255.5389C50.7464,-242.7186 39.0587,-224.614 33.8758,-206.4 26.8559,-181.7305 29.7309,-152.4555 33.6431,-131.3981"/>
<polygon fill="#000000" stroke="#000000" points="37.0946,-131.9896 35.6722,-121.4907 30.2369,-130.5851 37.0946,-131.9896"/>
<text text-anchor="middle" x="76.7971" y="-191.7" font-family="Times,serif" font-size="11.00" fill="#000000">When both queue </text>
<text text-anchor="middle" x="76.7971" y="-178.5" font-family="Times,serif" font-size="11.00" fill="#000000">and pool are empty</text>
</g>
<!-- STOP&#45;&gt;TIDYING -->
<g id="edge5" class="edge">
<title>STOP&#45;&gt;TIDYING</title>
<path fill="none" stroke="#000000" d="M130.3135,-170.3313C113.5368,-157.7928 91.0052,-140.9534 72.7058,-127.277"/>
<polygon fill="#000000" stroke="#000000" points="74.737,-124.4257 64.6316,-121.2427 70.5465,-130.0328 74.737,-124.4257"/>
<text text-anchor="middle" x="148.9421" y="-142.5" font-family="Times,serif" font-size="11.00" fill="#000000">When pool is empty</text>
</g>
<!-- TERMINATED -->
<g id="node5" class="node">
<title>TERMINATED</title>
<polygon fill="none" stroke="#000000" points="80.97,-36 .01,-36 .01,0 80.97,0 80.97,-36"/>
<text text-anchor="middle" x="40.49" y="-15" font-family="Times,serif" font-size="10.00" fill="#000000">TERMINATED</text>
</g>
<!-- TIDYING&#45;&gt;TERMINATED -->
<g id="edge6" class="edge">
<title>TIDYING&#45;&gt;TERMINATED</title>
<path fill="none" stroke="#000000" d="M40.49,-85.1313C40.49,-73.8354 40.49,-59.0487 40.49,-46.2289"/>
<polygon fill="#000000" stroke="#000000" points="43.9901,-46.0426 40.49,-36.0427 36.9901,-46.0427 43.9901,-46.0426"/>
<text text-anchor="middle" x="133.0424" y="-57.3" font-family="Times,serif" font-size="11.00" fill="#000000">When terminated() method has completed</text>
</g>
</g>
</svg>


<p>线程池状态和线程数使用同一个int变量来保存，一个int变量包含32个bit，高3为用于存放状态。RUNNING=111，SHUTDOWN=000，STOP=001，TIDYING=010，TERMINATED=011。</p>
<h2 id="线程池排队策略"><a href="#线程池排队策略" class="headerlink" title="线程池排队策略"></a>线程池排队策略</h2><p>线程池任务的排队常用的有3中策略。</p>
<p><strong>直接传递</strong>：采用同步队列<code>SynchronousQueue</code>来执行任务排队策略。每次任务入队都要等待另一个线程拿走该任务。当任务要入队时，如果没有线程立马来消费，入队就会失败<small><em>(SynchronousQueue.offer默认超时时间为0)</em></small>，就会新建一个线程来执行任务。直接传递策略通常要求maximumPoolSize设置为无限大来避免任务被拒绝。否则，当线程数达到上限时，新任务将会被拒绝。</p>
<ul>
<li><code>Executors#newCachedThreadPool()</code>就是使用这种策略，核心线程数为0，最大线程数是Integer.MAX_VALUE，线程keepAliveTime是1分钟。</li>
</ul>
<p><strong>无界队列</strong>：比如使用不设置最大容量的<code>LinkedBlockingQueue</code>。当核心线程已满时，新任务会在队列中等待。因此创建的线程数不会超过corePoolSize<small>（任务队列是无限大，maximumPoolSize不会起作用）</small>。如果任务经常会被阻塞，比如IO任务，将会导致耗尽系统内存。</p>
<ul>
<li><code>Executors#newFixedThreadPool(int nThreads)</code>就是使用的这种策略，最大线程数和核心线程数使用相同的值nThreads；</li>
<li><code>Executors#newSingleThreadExecutor()</code>也是这种策略，相当于nThreads=1；</li>
</ul>
<p><strong>有界队列</strong>：比如<code>ArrayBlockingQueue</code>。配合有限制的maximumPoolSize，有界队列可以防止资源耗尽的情况发生。但是队列的容量和maximumPoolSize两者必须做权衡：使用大容量队列和一个小的maximumPoolSize，可以减少对cpu、系统资源、上下文切换等资源的消耗，但是会明显降低吞吐量；使用小队列和大容量线程池，时刻保持cpu的忙碌状态，但是可能会遇到比较大的调度压力，也会降低吞吐量。</p>
<h2 id="参考文档"><a href="#参考文档" class="headerlink" title="参考文档"></a>参考文档</h2><p><a target="_blank" rel="noopener external nofollow noreferrer" href="https://www.cnblogs.com/zxporz/p/10940251.html">ThreadPoolExecutor线程池的keepAliveTime</a><br><a target="_blank" rel="noopener external nofollow noreferrer" href="https://www.cnblogs.com/qingquanzi/p/9018627.html">如何优雅的关闭Java线程池</a><br><a target="_blank" rel="noopener external nofollow noreferrer" href="https://blog.csdn.net/qq_26881739/article/details/80983495">线程池的三种队列区别：SynchronousQueue、LinkedBlockingQueue 和ArrayBlockingQueue</a><br><a target="_blank" rel="noopener external nofollow noreferrer" href="https://zhuanlan.zhihu.com/p/350067478">太完整了！这是我见过最详细的线程池讲解了</a><br><a target="_blank" rel="noopener external nofollow noreferrer" href="https://www.gangofcoders.net/solution/why-is-creating-a-thread-said-to-be-expensive/">Why is creating a Thread said to be expensive?</a></p>

    </div>

    
    
    

    <footer class="post-footer">
          <div class="post-tags">
              <a href="/tags/Android/" rel="tag"># Android</a>
              <a href="/tags/Java/" rel="tag"># Java</a>
          </div>

        

          <div class="post-nav">
            <div class="post-nav-item">
                <a href="/posts/73cf04e1.html" rel="prev" title="okhttp详解系列六：服务请求拦截器 CallServerInterceptor">
                  <i class="fa fa-angle-left"></i> okhttp详解系列六：服务请求拦截器 CallServerInterceptor
                </a>
            </div>
            <div class="post-nav-item">
                <a href="/posts/fd3db9c4.html" rel="next" title="Java CAS详解">
                  Java CAS详解 <i class="fa fa-angle-right"></i>
                </a>
            </div>
          </div>
    </footer>
  </article>
</div>






</div>
  </main>

  <footer class="footer">
    <div class="footer-inner">

  <div class="copyright">
    &copy; 
    <span itemprop="copyrightYear">2024</span>
    <span class="with-love">
      <i class="fa fa-heart"></i>
    </span>
    <span class="author" itemprop="copyrightHolder">Jason</span>
  </div>
  <div class="powered-by">由 <a href="https://hexo.io/" rel="noopener external nofollow noreferrer" target="_blank">Hexo</a> & <a href="https://theme-next.js.org/pisces/" rel="noopener external nofollow noreferrer" target="_blank">NexT.Pisces</a> 强力驱动
  </div>

    </div>
  </footer>

  
  <div class="back-to-top" role="button" aria-label="返回顶部">
    <i class="fa fa-arrow-up fa-lg"></i>
    <span>0%</span>
  </div>

<noscript>
  <div class="noscript-warning">Theme NexT works best with JavaScript enabled</div>
</noscript>


  
  <script src="https://cdnjs.cloudflare.com/ajax/libs/animejs/3.2.1/anime.min.js" integrity="sha256-XL2inqUJaslATFnHdJOi9GfQ60on8Wx1C2H8DYiN1xY=" crossorigin="anonymous"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/next-theme-pjax/0.6.0/pjax.min.js" integrity="sha256-vxLn1tSKWD4dqbMRyv940UYw4sXgMtYcK6reefzZrao=" crossorigin="anonymous"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/fancyapps-ui/5.0.24/fancybox/fancybox.umd.js" integrity="sha256-oyhjPiYRWGXaAt+ny/mTMWOnN1GBoZDUQnzzgC7FRI4=" crossorigin="anonymous"></script>
<script src="/js/comments.js"></script><script src="/js/utils.js"></script><script src="/js/motion.js"></script><script src="/js/next-boot.js"></script><script src="/js/pjax.js"></script>

  <script src="https://cdnjs.cloudflare.com/ajax/libs/hexo-generator-searchdb/1.4.1/search.js" integrity="sha256-1kfA5uHPf65M5cphT2dvymhkuyHPQp5A53EGZOnOLmc=" crossorigin="anonymous"></script>
<script src="/js/third-party/search/local-search.js"></script>


  <script class="next-config" data-name="mermaid" type="application/json">{"enable":true,"theme":{"light":"default","dark":"dark"},"js":{"url":"https://cdnjs.cloudflare.com/ajax/libs/mermaid/10.5.0/mermaid.min.js","integrity":"sha256-K7oJiQlDulzl24ZUFOywuYme1JqBBvQzK6m8qHjt9Gk="}}</script>
  <script type="module" src="/js/zenuml-definition-074a43fa.js"></script>
  <script type="module" src="/js/mermaid-zenuml.esm.min.mjs"></script>
  <script src="/js/third-party/tags/mermaid.js"></script>


  <script src="/js/third-party/fancybox.js"></script>



  




  

  <script class="next-config" data-name="enableMath" type="application/json">true</script><script class="next-config" data-name="mathjax" type="application/json">{"enable":true,"tags":"none","js":{"url":"https://cdnjs.cloudflare.com/ajax/libs/mathjax/3.2.2/es5/tex-mml-chtml.js","integrity":"sha256-MASABpB4tYktI2Oitl4t+78w/lyA+D7b/s9GEP0JOGI="}}</script>
<script src="/js/third-party/math/mathjax.js"></script>



</body>
</html>
